/*
 * Exploder
 * 
 * Tero Pyylampi (218437), Jussi Tuurinkoski (211594)
 *
 * MainEngine, which manages the screen switching from scene to scene
 * using possible fancy transition effects like fade in / out
 */

#include "MainEngine.h"
#include "Common.h"
#include "LuaInterface.h"
#include "splash/SplashScene.h"
#include "menu/MenuScene.h"
#include "game/GameScene.h"
#include "editor/EditorScene.h"
#include "misc/UserData.h"

#include "cocos2d.h"
#include "SimpleAudioEngine.h"

using namespace cocos2d;

// constructor
MainEngine::MainEngine() : mCurrentScene( 0 ), mCurrentSceneType( SCENE_INVALID ) {
	CCDirector *pDirector = CCDirector::sharedDirector();

	// set fps from common-header
	pDirector->setDisplayFPS( false );
	// set frame length
	pDirector->setAnimationInterval( 1.0 / 60 );
	pDirector->setDepthTest( true );

	// init random number generator
	srand( static_cast< unsigned int >( time( 0 ) ) );

	// init lua interface
	mLuaInterface = new LuaInterface();
	// load user data
	mUserData = new UserData();

	// start with the splash scene
	initializeSplashScene();
}

// destructor
MainEngine::~MainEngine() {

}

// initializes the splash screen
void MainEngine::initializeSplashScene() {
	mCurrentScene = new SplashScene( this );
	mCurrentSceneType = SCENE_SPLASH;
	initializeScene( mCurrentScene );
}

// current scene finished execution, let this object decide what to do
void MainEngine::sceneFinishedExecution() {
	// choose scene to be used
	switch( mCurrentSceneType ) {
	// after splash scene, show loading
	case SCENE_SPLASH: {
			CCDirector::sharedDirector()->purgeCachedData();
			mCurrentScene = new MenuScene( this );
			mCurrentSceneType = SCENE_MENU;
			break;
		}
	// after menu show game scene
	case SCENE_MENU: {
			mCurrentScene = new GameScene( this, 1 );
			mCurrentSceneType = SCENE_GAME;
			break;
		}
	// after game show menu scene
	case SCENE_GAME: {
			mCurrentScene = new MenuScene( this );
			mCurrentSceneType = SCENE_MENU;
			break;
		}
	// after editor return to the menu
	case SCENE_EDITOR: {
			mCurrentScene = new MenuScene( this );
			mCurrentSceneType = SCENE_MENU;
			break;
		}
	};

	// launch scene
	initializeSceneUsingTransition( mCurrentScene );
}

// current scene finished execution and suggests the next scene to be loaded
void MainEngine::sceneFinishedExecution( cocos2d::CCScene *newScene, Scene sceneType ) {
	mCurrentScene = newScene;
	mCurrentSceneType = sceneType;

	// launch scene
	initializeSceneUsingTransition( mCurrentScene );
}

// start the specific scene
void MainEngine::initializeScene( cocos2d::CCScene *scene ) {
	CCDirector *pDirector = CCDirector::sharedDirector();

	// start scene
	if( pDirector->getRunningScene() == 0 )
		pDirector->runWithScene( scene );
	else
		pDirector->replaceScene( scene );

}

// start the specific scene using a transition effect
void MainEngine::initializeSceneUsingTransition( cocos2d::CCScene *scene ) {
	CCDirector *pDirector = CCDirector::sharedDirector();

	// transition scene
	CCScene *pScene = CCTransitionFade::transitionWithDuration( 0.5f, scene, ccBLACK );

	// start scene
	pDirector->replaceScene( pScene );
}

// pause event from the main engine (eg. incoming call)
void MainEngine::applicationPaused() {
	// set paused state
	CCDirector::sharedDirector()->pause();
	// pause background music
	CocosDenshion::SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
	CocosDenshion::SimpleAudioEngine::sharedEngine()->pauseAllEffects();
}

// resume event from the main engine
void MainEngine::applicationResumed() {
	CCDirector::sharedDirector()->resume();
	CocosDenshion::SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();
	CocosDenshion::SimpleAudioEngine::sharedEngine()->resumeAllEffects();
}

// restart whole application 
void MainEngine::restartApplication() {
	// delete saved textures etc
	CCDirector::sharedDirector()->purgeCachedData();
	initializeSplashScene();
}

// get lua implementation
LuaInterface *MainEngine::getLuaInterface() {
	return mLuaInterface;
}

// get saved user data
UserData *MainEngine::getUserData() {
	return mUserData;
}
